
#ifndef ASSEMBLER_MACHINE_STATE_
#define ASSEMBLER_MACHINE_STATE_

#include <stack>

namespace assembler {

class MachineStateException {
public:
  virtual const char *error() = 0;
};

class MachineStateStackUnderflowException
  : public MachineStateException {
public:
  virtual const char *error() {
    return "Stack overflow in machine state";
  }
};

class MachineStateInvalidRegisterIdException
  : public MachineStateException {
public:
  MachineStateInvalidRegisterIdException(int id)
    : id_(id) {}
  
  virtual const char *error() {
    return "Invalid register id";
  }

  int id() const { return id_; }
private:
  int id_;
};

// MachineState keeps all registers' values and machine stack. It implements
// register fetching and assignment and stack operations.
//
// Two exception classes above denote the possible execution exceptions for 
// this class
class MachineState {
public:
  static const int RegisterCount = 10;

  MachineState();

  double reg(int id) const;

  void set_reg(int id, double value);

  void push(double value);

  void pop(int id);

private:
  // No copy, no assigmnent:
  MachineState(MachineState &){}
  MachineState &operator=(MachineState &){}

  static void CheckRegisterIdAllowed(int id);

  double reg_[RegisterCount];
  std::stack<double> stack_;
};

}  // namespace assembler

#endif